#include "UDPScanner.h"
#include <winsock2.h>
#include <winsock.h>
#include <iostream>
#include <assert.h>
#include <QVector>
#include "Common.h"

#define IPAddress "10.4.16.113"

UDPScanner::UDPScanner()
{
    Init();
}

void UDPScanner::UDP_Scan(const char* DestIP, unsigned short StartPort, unsigned short EndPort)
{
    u_long ulDestIP = INADDR_NONE;
    if(strcmp("127.0.0.1", DestIP) == 0)
    {
        ulDestIP = inet_addr(IPAddress);
    }
    else
    {
        ulDestIP = inet_addr(DestIP);
    }

    if(ulDestIP == INADDR_NONE)
    {
        hostent* pHostent = gethostbyname(DestIP);
        if(pHostent)
        {
            ulDestIP = (*(in_addr*)pHostent->h_addr).s_addr;
        }
        else
        {
            assert(false);
            std::cout << "错误" << std::endl;
        }
    }

    SOCKADDR_IN addrCli;
    addrCli.sin_family = AF_INET;
    addrCli.sin_addr.s_addr = ulDestIP;

    char buffer[1] = {};

    char recvBuf[256] = {0};


    SOCKADDR_IN addr;
    int len = sizeof(addr);

    for(unsigned short port = StartPort; port <= EndPort; ++port)
    {
        addrCli.sin_port = htons(port);
        for(int i = 0 ; i < 10; ++i)
            sendto(sock, buffer, sizeof(buffer), 0, (SOCKADDR*)&addrCli, sizeof(addrCli));

        int size = recvfrom(sock, recvBuf, sizeof(recvBuf), 0, (SOCKADDR*)&addr, &len);
        if(size == -1)
        {
            QVector<QString> item(4);
            item[0] = inet_ntoa(addrCli.sin_addr);
            item[1] = QString::number(port);
            item[2] = "Close";
            item[3] = ::showservice(QString::number(port));
            OnResult.Broadcast(item);
            closesocket(sock);
        }
    }
}

void UDPScanner::Init()
{
    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    addrSrv.sin_family = AF_INET;
    addrSrv.sin_port = htons(6002);

    // 绑定套接字
    bind(sock, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));

    int nTimeout = 1000;
    //设置发送超时为1000ms
    if (SOCKET_ERROR == setsockopt( this->sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&nTimeout, sizeof(int)))
    {
        fprintf(stderr, "Set SO_SNDTIMEO error !\n");
    }

    //设置接收超时为1000ms
    if (SOCKET_ERROR == setsockopt( this->sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeout, sizeof(int)))
    {
        fprintf(stderr, "Set SO_RCVTIMEO error !\n");
    }
}
